
#include "CPU_const.h"



/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*              C L A S S    C O N S T R U C T O R   &   D E S T R U C T O R                        */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
UARTbuf::UARTbuf(uint buf_size, unsigned char volatile *pUTHR)
{
//buffer create:
  BufFree();    pBufIn = (char *) pvPortMalloc(buf_size);   pBufOut = (char *) pvPortMalloc(buf_size);
  if(pBufIn==NULL || pBufOut==NULL)
    {BufFree(); pBufIn = pBufOut = (char *)&trash; bufSize = 0;} else {bufSize = buf_size;}
//QUEUE & MUTEX create:  
  qIndI = xQueueCreate(1, sizeof(uint));    //qIndO = xQueueCreate(1, sizeof(uint));
  qBrdI = xQueueCreate(1, sizeof(uint));    //qBrdOISR = xQueueCreate(1, sizeof(uint));
  mWrBufOen = xSemaphoreCreateMutex();
//variables initialization:
  pUnTHR = pUTHR;
  indI = indO = brdO = 0;  brdI = brdOISR = bufSize; TransON = false; 
// 
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/

/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/





/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*                I N P U T   &   O U T P U T   B U F F E R'S   W R I T E   &   R E A D             */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//   Write Input Buffer form UART ISR
void UARTbuf::WrBufIn(char DataIn)   { *(pBufIn+indI) = DataIn;  if(indI!=brdI) next(&indI); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//   Read Input Buffer form User Task
char UARTbuf::RdBufIn(uint indx)   { if(indx>=bufSize) {return 0;} else {return *(pBufIn+indx);} }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//   Write Output Buffer form User Task
void UARTbuf::WrBufOut(char DataOut)
{ if(bufSize) while(indO==brdO && TransON);  *(pBufOut+brdO) = DataOut;  next(&brdO); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//   Read Output Buffer form UART ISR
bool UARTbuf::RdBufOut(void)
{ 
  if(indO!=brdOISR)
    {*pUnTHR = *(pBufOut+indO); next(&indO); return true;}  else  {TransON = false; return false; }
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/


bool UARTbuf::XORBufOut(uint indx, char DataIn)
{ if(indx==brdO) {return false;} else {*(pBufOut+indx) ^=DataIn; return true;} }




/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*                            Q U E U E'S   S E N D   &   R E C E I V E                             */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::SendIndI(void) 
{ 
  xQueueReceiveFromISR(qIndI,&trash,&xHiPriorTaskWoken);
  xQueueSendFromISR(qIndI,&indI,&xHiPriorTaskWoken);
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::RecieveIndI(uint *pIndx)   { xQueueReceive(qIndI, pIndx, portMAX_DELAY); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
bool UARTbuf::RecieveIndI(uint *pIndx, portTickType xTicksToWait)
{ 
  if( xQueueReceive(qIndI, pIndx, xTicksToWait)==errQUEUE_EMPTY ) {return false;} else {return true;}
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::SendBrdI(uint Indx)   { xQueueReceive(qBrdI,&trash,0);   xQueueSend(qBrdI,&Indx,0); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::RecieveBrdI(void)  { xQueueReceiveFromISR(qBrdI, &brdI, &xHiPriorTaskWoken); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/





/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*                              D I F E R E N T   F U N C T I O N S                                 */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::ResetBrdI(void)   { SendBrdI(bufSize); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::SetBrdOISR(void)
{ 
  if(bufSize) while(indO==brdO && TransON);
  taskENTER_CRITICAL(); brdOISR = brdO; taskEXIT_CRITICAL();
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
uint UARTbuf::GetBrdO(void)   { return brdO; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
uint UARTbuf::GetBufSize(void)   { return bufSize; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::StartTransmite(void)   { if(!TransON) { TransON = true; RdBufOut(); } }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::next(uint *pINDX)  { ++*pINDX; if(*pINDX>=bufSize) *pINDX=0; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
uint UARTbuf::shift(uint Xbgn, uint step)
{ Xbgn +=step; if(Xbgn>=bufSize) Xbgn -= bufSize; return Xbgn; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
uint UARTbuf::CountBytes(uint Xbgn, uint Xend)
{ if(Xbgn>Xend) {return (bufSize-Xbgn+Xend);} else {return (Xend-Xbgn);}; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
bool UARTbuf::CheckSize(uint NofBytes)   { if(NofBytes>bufSize) {return false;} else {return true;}; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/





/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*                I N P U T   &   O U T P U T   C R C 1 6   C A L C U L A T I O N                   */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
bool UARTbuf::CRC16in(uint Xbgn, uint Xend)
{ if( CRC16(pBufIn,Xbgn,Xend) ) {return false;} else {return true;}; }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::CRC16out(uint Xbgn)
{ uint crc = CRC16(pBufOut,Xbgn,brdO);   WrBufOut((char)crc); WrBufOut(crc>>8); }
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/





/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*                                P R I V A T E   F U N C T I O N S                                 */
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
void UARTbuf::BufFree(void)
{
  if(pBufIn !=NULL) {vPortFree(pBufIn);  pBufIn = NULL; }
  if(pBufOut!=NULL) {vPortFree(pBufOut); pBufOut = NULL;}
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
//
uint UARTbuf::CRC16(char *pBuf, uint Xbgn, uint Xend)
{ uint ui, crc=0x0000FFFF;
  while(Xbgn!=Xend)
   { 
     crc ^= *(pBuf+Xbgn);  next(&Xbgn);
     for(ui=0; ui<8; ++ui) { if(crc&0x0001) {crc=crc>>1; crc^=0xA001;} else {crc=crc>>1;}; };
    };
  return crc;
}
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/